/**
 * 文章服务实现类，提供文章相关的业务逻辑处理。
 */
package org.inspiration.dudu.content.service.impl;

import lombok.RequiredArgsConstructor;
import org.inspiration.dudu.common.constant.RedisConstant;
import org.inspiration.dudu.common.util.FileUtil;
import org.inspiration.dudu.common.util.RedisUtil;
import org.inspiration.dudu.content.mapper.ArticleMapper;
import org.inspiration.dudu.content.model.dto.ArticleDTO;
import org.inspiration.dudu.content.model.entity.ArticleEntity;
import org.inspiration.dudu.content.model.vo.ArticleSimpleVO;
import org.inspiration.dudu.content.model.vo.ArticleVO;
import org.inspiration.dudu.content.service.ArticleService;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
@RequiredArgsConstructor
public class ArticleServiceImpl implements ArticleService {

    private final ArticleMapper articleMapper;
    private final RedisUtil redisUtil;
    private final RabbitTemplate rabbitTemplate;

    @Value("${dudu.rabbitmq.exchanges.like-exchange.name}")
    private String likeExchangeName;

    @Value("${dudu.rabbitmq.exchanges.like-exchange.queues.article-like-queue.routing-key}")
    private String articleLikeRoutingKey;



    /**
     * 创建文章
     *
     * @param articleEntity 文章实体
     */
    @Override
    public void createArticle(ArticleEntity articleEntity) {
        articleMapper.createArticle(articleEntity);
    }

    /**
     * 根据ID查找文章
     *
     * @param id 文章ID
     * @return 文章视图对象
     */
    @Override
    public ArticleVO getArticleById(String id) {
        ArticleEntity articleEntity = redisUtil.queryHashCache(RedisConstant.ARTICLE_KEY_PREFIX, id, ArticleEntity.class, articleMapper::getArticleById, 60L, TimeUnit.SECONDS);
        return transToVO(articleEntity);
    }

    /**
     * 将ArticleDTO转换为ArticleEntity
     *
     * @param articleDTO      文章数据传输对象
     * @param contentFilePath 内容文件路径
     * @param uuid            文章唯一标识
     * @return 文章实体
     */
    @Override
    public ArticleEntity transToEntity(ArticleDTO articleDTO, String contentFilePath, String uuid) {
        ArticleEntity articleEntity = new ArticleEntity();
        BeanUtils.copyProperties(articleDTO, articleEntity);
        articleEntity.setContentFilePath(contentFilePath);
        articleEntity.setId(uuid);
        return articleEntity;
    }

    /**
     * 将ArticleEntity转换为ArticleVO
     *
     * @param articleEntity 文章实体
     * @return 文章视图对象
     */
    @Override
    public ArticleVO transToVO(ArticleEntity articleEntity) {
        ArticleVO articleVO = new ArticleVO();
        BeanUtils.copyProperties(articleEntity, articleVO);
        String content = FileUtil.readStringFromFile(articleEntity.getContentFilePath());
        articleVO.setContent(content);
        return articleVO;
    }

    /**
     * 获取最近的文章列表
     *
     * @param pageNum  页码
     * @param pageSize 每页大小
     * @return 文章简单视图对象列表
     */
    @Override
    public List<ArticleSimpleVO> getPublishedArticlesOrderByDESC(int pageNum, int pageSize) {
        List<ArticleSimpleVO> res = new ArrayList<>();
        List<ArticleEntity> list = articleMapper.getPublishedArticlesOrderByDESC((pageNum - 1) * pageSize, pageSize);
        for (ArticleEntity articleEntity : list) {
            res.add(transToSimpleVO(articleEntity));
        }
        return res;
    }

    /**
     * 将ArticleEntity转换为ArticleSimpleVO
     *
     * @param articleEntity 文章实体
     * @return 文章简单视图对象
     */
    @Override
    public ArticleSimpleVO transToSimpleVO(ArticleEntity articleEntity) {
        ArticleSimpleVO articleSimpleVO = new ArticleSimpleVO();
        BeanUtils.copyProperties(articleEntity, articleSimpleVO);
        return articleSimpleVO;
    }

    @Override
    public ArticleSimpleVO transToSimpleVO(ArticleVO articleVO) {
        ArticleSimpleVO articleSimpleVO = new ArticleSimpleVO();
        BeanUtils.copyProperties(articleVO, articleSimpleVO);
        return articleSimpleVO;
    }

    /**
     * 增加文章的点赞数
     *
     * @param contentId 文章内容ID
     */
    @Override
    public void increaseLikeCount(String contentId) {
        //修改缓存
        String key = RedisConstant.ARTICLE_KEY_PREFIX + contentId;
        redisUtil.incrementHashFieldWithLua(key, "likeCount");

        //异步更新数据库
        Map<String, Object> map = new HashMap<>();
        map.put("contentId", contentId);
        map.put("action", "like");
        rabbitTemplate.convertAndSend(likeExchangeName, articleLikeRoutingKey, map);

    }

    /**
     * 减少文章的点赞数
     *
     * @param contentId 文章内容ID
     */
    @Override
    public void decreaseLikeCount(String contentId) {
        //更新缓存
        String key = RedisConstant.ARTICLE_KEY_PREFIX + contentId;
        redisUtil.decrementHashFieldWithLua(key, "likeCount");

        //异步更新数据库
        Map<String, Object> map = new HashMap<>();
        map.put("contentId", contentId);
        map.put("action", "unlike");
        rabbitTemplate.convertAndSend(likeExchangeName, articleLikeRoutingKey, map);
    }


    /**
     * 根据内容ID获取用户ID
     *
     * @param contentId 文章内容ID
     * @return 用户ID
     */
    @Override
    public Long getUserIdByContentId(String contentId) {
        return getArticleById(contentId).getUserId();
    }

    /**
     * 增加文章的收藏数
     *
     * @param contentId 文章内容ID
     */
    @Override
    public void increaseFavoriteCount(String contentId) {
        articleMapper.increaseFavoriteCount(contentId);
        // 删缓存
        String key = RedisConstant.ARTICLE_KEY_PREFIX + contentId;
        redisUtil.deleteKey(key);
    }

    /**
     * 减少文章的收藏数
     *
     * @param contentId 文章内容ID
     */
    @Override
    public void decreaseFavoriteCount(String contentId) {
        articleMapper.decreaseFavoriteCount(contentId);
        String key = RedisConstant.ARTICLE_KEY_PREFIX + contentId;
        redisUtil.deleteKey(key);

    }


    /**
     * 增加文章的评论数
     *
     * @param contentId 文章内容ID
     */
    @Override
    public void increaseCommentCount(String contentId) {
        articleMapper.increaseCommentCount(contentId);
        String key = RedisConstant.ARTICLE_KEY_PREFIX + contentId;
        redisUtil.deleteKey(key);
    }

    @Override
    public List<ArticleSimpleVO> getPublishedArticlesByUserIdOrderByDESC(Long userId, Integer pageNum, Integer pageSize) {
        List<ArticleSimpleVO> res = new ArrayList<>();
        List<ArticleEntity> list = articleMapper.getPublishedArticlesByUserIdOrderByDESC(userId, (pageNum - 1) * pageSize, pageSize);
        for(ArticleEntity articleEntity : list) {
            res.add(transToSimpleVO(articleEntity));
        }
        return res;
    }

    @Override
    public List<ArticleSimpleVO> getDraftArticlesByUserIdOrderByDESC(Long userId, Integer pageNum, Integer pageSize) {
        List<ArticleSimpleVO> res = new ArrayList<>();
        List<ArticleEntity> list = articleMapper.getDraftArticlesByUserIdOrderByDESC(userId, (pageNum - 1) * pageSize, pageSize);
        for(ArticleEntity articleEntity : list) {
            res.add(transToSimpleVO(articleEntity));
        }
        return res;
    }

    @Override
    public void updateArticle(ArticleEntity articleEntity) {
        articleMapper.updateArticle(articleEntity);
    }

    @Override
    public void updateArticleStatus(String id, String status) {
        articleMapper.updateArticleStatus(id, status);
    }

    @Override
    public List<ArticleSimpleVO> getArticlesByUserIdAndKeyWordOrderByDESC(Long userId, String keyWord, Integer pageNum, Integer pageSize) {
        return articleMapper.getArticlesByUserIdAndKeyWordOrderByDESC(userId, keyWord, (pageNum - 1) * pageSize, pageSize);
    }

    @Override
    public List<ArticleSimpleVO> getPublishedArticlesByKeyWordOrderByDESC(String keyWord, Integer pageNum, Integer pageSize) {
        return articleMapper.getPublishedArticlesByKeyWordOrderByDESC(keyWord, (pageNum - 1) * pageSize, pageSize);
    }


}
